const URI = require('urijs');

class HttpPromise extends Promise {
  request;
  abort() {
    if (request) {
      request.abort()
    }
  }
}
class Http {
  
  options;
  tknIncludePath; // 使用token的路径
  tknExcludePath;  // 不使用token的路径
  domain; // 域名
  //
  header = {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  };
  //拦截器
  interceptor = {
    request: (options) => options,
    response: (response) => {
      if (response.statusCode === 200) {
        return response.data;
      } else {
        let error = new Error(response.errMsg);
        error.code = response.statusCode;
        error.errMsg = response.errMsg;
        throw error;
      }
    }
  };

  constructor(options) {
    this.domain = options.domain;
    this.tknIncludePath = options.tknIncludePath;
    this.tknExcludePath = options.tknExcludePath;
    this.header = {
      ...this.header,
      ...options?.header || {}
    };
    this.interceptor = {
      ...this.interceptor,
      ...options?.interceptor || {}
    };
    this.options = options;
  }

  static instance(options) {
    return new this(options);
  }

  setHeader(key, value) {
    let obj = {};
    if (typeof key == 'string') {
      obj = {
        [key]: value
      };
    } else {
      obj = key;
    }
    this.header = {
      ...this.header,
      ...obj
    }
  }

  get(url, query, options = {}) {
    const { token, encrypt, ...rest } = options;
    return this.request({
      ...rest,
      url,
      query,
      method: 'GET',
    })
  }

  post(url, data, options = {}) {
    return this.request({
      ...options,
      url,
      data,
      method: 'POST',
    })
  }

  put(url, data, options = {},token=false,encrypt=false) {
    return this.request({
      ...options,
      url,
      data,
      method: 'PUT',
    })
  }

  patch(url, data, options = {},token=false,encrypt=false) {
    return this.request({
      ...options,
      url,
      data,
      method: 'PATCH',
    })
  }

  delete(url, data, options = {}) {
    return this.request({
      ...options,
      url,
      data,
      method: 'DELETE',
    })
  }

  upload(url, name, filePath, options = {}) {
    return this.request({
      ...options,
      url,
      name,
      filePath,
      method: 'UPLOAD',
    })
  }

  download(url, filePath, options = {}) {
    return this.request({
      ...options,
      url,
      filePath,
      method: 'DOWNLOAD',
    })
  }

  request(options) {
    var promise = new HttpPromise(async (resolve, reject) => {
      var url = (URI(options.url).is('absolute') ? URI(options.url) : URI(this.domain + options.url)).addQuery(options.query || {}).toString();
      
      // 移除多余参数
      delete options.query;
      delete options.url;
      
      var header = {
        ...this.header,
        ...options.header || {}
      };
      
      delete options.header;
      
      let opts = {
        ...this.options,
        ...options,
        header,
        url,
        checkUrl:this.checkUrl
      }
      
      if (this.interceptor.request) {
        opts = await this.interceptor.request.call(this, opts);
        delete opts.checkUrl;
      }
      
      opts = {
        ...opts,
        success: async (res) => {
          if (this.interceptor.response) {
            if (typeof res.data == 'string') {
              try {
                res.data = JSON.parse(res.data);
              } catch (e) {}
            }
            try {
              let response = await this.interceptor.response(res);
              resolve(response);
            } catch (e) {
              reject(e);
            }
          } else {
            resolve(res);
          }
        },
        fail: (res) => {
          reject(res);
        }
      }

      let request;
      if (opts.method == 'UPLOAD') {
        delete opts['Content-Type'];
        request = uni.uploadFile(opts)
      } else if (opts.method == 'DOWNLOAD') {
        request = uni.downloadFile(opts)
      } else {
        request = uni.request(opts);
      }

      setTimeout(() => {
        //promise还未赋值，只能使用异步，毕竟不会马上中断
        promise.request = request;
      }, 1)
    });
    return promise;
  }
  
  checkUrl(url, path) {
      
      if(!path){
        return false;
      }
      
      //    如果 path 是字符串
      if (typeof path === 'string') {
          return url.includes(path);
      }
  
      // 如果 path 是数组
      if (Array.isArray(path)) {
          return path.some(path => url.includes(path));
      }
  
      // 如果 path 是正则表达式
      if (path instanceof RegExp) {
          return path.test(url);
      }
  
      // 如果 path 是其他类型，返回 false
      return false;
  }
}

export default Http;
